﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GalleryDefinition.h"
#include "GbmpNew.h"
#include "GalleryEvent.h"
#include "FindByIdPredicate.h"
#include "GalleryItemDefinition.h"
#include "ControlDefinitionChangeEvent.h"
#include <algorithm>
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

gcmp::GalleryDefinition::GalleryDefinition(const std::wstring& id, const std::wstring& caption, int columnCount, int itemWidth /*= 16*/, int itemHeight /*= 16*/)
    : m_pControlDefinition(NEW_AS_OWNER_PTR(ControlDefinition, id, caption, caption))
    , m_itemWidth(itemWidth)
    , m_itemHeight(itemHeight)
    , m_currentIndex(-1)
    , m_columnCount(columnCount)
{
    m_event = NEW_AS_OWNER_PTR(GalleryEvent, L"GalleryEvent", this);
    m_pDefinitionChangeEvent = NEW_AS_OWNER_PTR(ControlDefinitionChangeEvent, L"GalleryDefineChangeEvent", this);
}

gcmp::GalleryDefinition::~GalleryDefinition()
{

}

bool gcmp::GalleryDefinition::SetCurrentGalleryItem(const std::wstring& id)
{
    int index = -1;
    if (!id.empty()) {
        auto search = std::find_if(m_pGalleryItems.begin(), m_pGalleryItems.end(), FindPtrBIdPredicate<OwnerPtr<GalleryItemDefinition>>(id));
        DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_pGalleryItems.end(), L"没找到Item",L"GDMPLab",L"2024-03-30");
        index = static_cast<int>(std::distance(m_pGalleryItems.begin(), search));
    }
    
    if (m_currentIndex != index)
    {
        SetCurrentIndex(index);
        ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Other);
        arguments.SetModifyControlDefinitionId(id);
        m_pDefinitionChangeEvent->Emit(&arguments);
    }
    return true;
}

bool gcmp::GalleryDefinition::SetColumnCount(int columnCount)
{
    if (columnCount < 1)
    {
        return false;
    }
    if (m_columnCount != columnCount)
    {   
        m_columnCount = columnCount;
        ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Other);
        m_pDefinitionChangeEvent->Emit(&arguments);
    }
    return true;
}

int gcmp::GalleryDefinition::GetColumnCount() const
{
    return m_columnCount;
}

const IGalleryItemDefinition* gcmp::GalleryDefinition::GetCurrentItem() const
{
    if (m_currentIndex < 0)
    {
        return nullptr;
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(m_currentIndex < (int)m_pGalleryItems.size(), L"index不正确",L"GDMPLab",L"2024-03-30");
    return const_cast<GalleryItemDefinition*>(m_pGalleryItems[m_currentIndex].get());
}

gcmp::IGalleryItemDefinition* gcmp::GalleryDefinition::GetItem(int index) const
{
    if (index < 0)
    {
        return nullptr;
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(index < (int)m_pGalleryItems.size(), L"索引不正确",L"GDMPLab",L"2024-03-30");
    return const_cast<GalleryItemDefinition*>(m_pGalleryItems[index].get());
}

bool gcmp::GalleryDefinition::InsertItem(const std::wstring& beforeId, const std::wstring& id, const std::wstring& caption, const std::wstring& tooltip, const std::wstring& iconPath, const Any& userData)
{
    auto search = std::find_if(m_pGalleryItems.begin(), m_pGalleryItems.end(), FindPtrBIdPredicate<OwnerPtr<GalleryItemDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search == m_pGalleryItems.end(), L"m_pGalleryItems内GalleryItem名字必须唯一",L"GDMPLab",L"2024-03-30");

    search = std::find_if(m_pGalleryItems.begin(), m_pGalleryItems.end(), FindPtrBIdPredicate<OwnerPtr<GalleryItemDefinition>>(beforeId));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_pGalleryItems.end(), L"没找到插入参考的Item",L"GDMPLab",L"2024-03-30");
    int index = static_cast<int>(std::distance(m_pGalleryItems.begin(), search));
    
    OwnerPtr<GalleryItemDefinition> pGalleryItemDefinition = NEW_AS_OWNER_PTR(GalleryItemDefinition, id, caption, tooltip, iconPath, userData);
    GalleryItemDefinition* pGalleryItem = pGalleryItemDefinition.get();
    
    m_pGalleryItems.emplace(search, TransferOwnership(pGalleryItemDefinition));
   
    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Insert);
    arguments.SetDeleteOrInsertControlDefinitionIndex(index);
    arguments.SetControlDefinition(pGalleryItem);
    m_pDefinitionChangeEvent->Emit(&arguments);
    return true;
}

bool gcmp::GalleryDefinition::DeleteItem(const std::wstring& id)
{
    auto search = std::find_if(m_pGalleryItems.begin(), m_pGalleryItems.end(), FindPtrBIdPredicate<OwnerPtr<GalleryItemDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_pGalleryItems.end(), L"找不到菜单项",L"GDMPLab",L"2024-03-30");
    int index = static_cast<int>(std::distance(m_pGalleryItems.begin(), search));
    m_pGalleryItems.erase(search);
    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Delete);
    arguments.SetDeleteOrInsertControlDefinitionIndex(index);
    m_pDefinitionChangeEvent->Emit(&arguments);
    return true;
}

bool gcmp::GalleryDefinition::DeleteAllItems()
{
    m_pGalleryItems.clear();
    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::DeleteAll);
    m_pDefinitionChangeEvent->Emit(&arguments);
    return true;
}

gcmp::IControlDefinitionChangeEvent* gcmp::GalleryDefinition::GetControlDefinitionChangeEvent() const
{
    return const_cast<ControlDefinitionChangeEvent*>(m_pDefinitionChangeEvent.get());
}

std::vector<IGalleryItemDefinition*> gcmp::GalleryDefinition::GetAllItems() const
{
    std::vector<IGalleryItemDefinition*> items;
    for (auto& item : m_pGalleryItems)
    {
        items.push_back(const_cast<GalleryItemDefinition*>(item.get()));
    }
    return items;
}


bool gcmp::GalleryDefinition::AddItem(const std::wstring& id, const std::wstring& caption, const std::wstring& tooltip, const std::wstring& iconPath, const Any& userData)
{
    auto search = std::find_if(m_pGalleryItems.begin(), m_pGalleryItems.end(), FindPtrBIdPredicate<OwnerPtr<GalleryItemDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search == m_pGalleryItems.end(), L"m_pGalleryItems内GalleryItem名字必须唯一",L"GDMPLab",L"2024-03-30");

    OwnerPtr<GalleryItemDefinition> pGalleryItemDefinition = NEW_AS_OWNER_PTR(GalleryItemDefinition, id, caption, tooltip, iconPath, userData);
    GalleryItemDefinition* pGalleryItem = pGalleryItemDefinition.get();
    m_pGalleryItems.emplace_back(TransferOwnership(pGalleryItemDefinition));

    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Add);
    arguments.SetControlDefinition(pGalleryItem);
    m_pDefinitionChangeEvent->Emit(&arguments);

    return true;
}

gcmp::IGalleryItemDefinition* gcmp::GalleryDefinition::GetItem(const std::wstring& id) const
{
    int index = GetItemIndex(id);
    return GetItem(index);
}

int gcmp::GalleryDefinition::GetItemIndex(const std::wstring& id) const
{
    auto search = std::find_if(m_pGalleryItems.begin(), m_pGalleryItems.end(), FindPtrBIdPredicate<OwnerPtr<GalleryItemDefinition>>(id));
    if (search == m_pGalleryItems.end())
    {
        return -1;
    }

    int index = static_cast<int>(std::distance(m_pGalleryItems.begin(), search));
    return index;
}